/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.arc.state;

import arc.ArcBase;
import com.jme3.network.serializing.Serializable;

/**
 *
 * @author Adam
 */
@Serializable
public abstract class AbstractState {
    protected static byte stateIndexMask = (byte)15;
    protected static byte nextStateMask  = (byte)240;
    private byte[] stateData           = null;
    protected volatile byte   currentStateIndex   = -1;
    
    public AbstractState()
    {}
    public AbstractState(byte[] initialState)
    {        
        currentStateIndex = 0;
        
        initializeStateData(initialState);
        
        stateData = initialState;
    }
    
    abstract public void updateState(ArcBase app, ArcBase.Type type, Object[] params);
    
    public void nextState() {
        currentStateIndex = getNextState();
    }
    
    public byte getNextState() {
        if(getMask() == -1) return -1;
        return (byte)((getMask() & nextStateMask) >> 4);
    }

    public byte getMask() {
        if(currentStateIndex == -1) return -1;
        return stateData[currentStateIndex];
    }

    public byte getIndex() {
        if(getMask() == -1) return -1;
        return (byte)(getMask() & stateIndexMask);
    }

    public byte getMaskByIndex(byte stateIndex) {
        if(stateIndex < 0 || stateIndex >= stateData.length)
        {
            throw new ArrayIndexOutOfBoundsException(stateIndex);
        }
        
        return stateData[stateIndex];
    }

    public void initializeStateData(byte[] stateData) {
        for(int i = 0; i < stateData.length; i++)
        {
            int nextIndex = (stateData[i] & nextStateMask) >> 4;
            if(nextIndex >= stateData.length || nextIndex < 0)
            {
                throw new ArrayIndexOutOfBoundsException(nextIndex);
            }
        }
    }

    public void forceState(byte stateIndex) {
        currentStateIndex = (byte)(getMaskByIndex(stateIndex) & stateIndexMask);
    }

}
